package ru.spbu.math.seabattle.server.jms;

import java.io.Serializable;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;

import ru.spbu.math.seabattle.client.IClient;
import ru.spbu.math.seabattle.client.jms.common.JmsQueueHelper;
import ru.spbu.math.seabattle.client.messages.*;

import ru.spbu.math.seabattle.entity.GameResult;
import ru.spbu.math.seabattle.entity.PlayerID;
import ru.spbu.math.seabattle.entity.TurnResult;

import ru.spbu.math.seabattle.server.IServer;
import ru.spbu.math.seabattle.server.jms.gui.ServerGUI;
import ru.spbu.math.seabattle.server.messages.*;

public class SuperMegaServerWrapper extends AbstractJMSServer {

	public static final String SERVER_ADDRESS = "tcp://0.0.0.0:9001";
	public static final String SERVER_NAME = "super-mega-server";
	public static final String QUEUE_NAME = "super-mega-queue";
	
	public SuperMegaServerWrapper() {
		super(SERVER_ADDRESS, SERVER_NAME, QUEUE_NAME);
	}
	
	public static void main(String[] args) throws Exception {
		new ServerGUI(new SuperMegaServerWrapper());
	}
	
	private final IServer wrappedServer = new SuperMegaServer();
	
	private class JmsClient implements IClient {

		private static final long serialVersionUID = 1L;
		
		private final JmsQueueHelper queue;
		
		public JmsClient(Destination location) throws JMSException {
			
			queue = new JmsQueueHelper();
			queue.start(SERVER_ADDRESS, location);
		}
		
		@Override
		public void onEnemyTurnEnded(TurnResult result) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onEnemyTurnEnded to " + queue);
				queue.send(new OnEnemyTurnEndedMessage(result));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onEnemyTurnStarted() {
			
			try {
				System.out.println("SERVER WRAPPER: sending onEnemyTurnStarted to " + queue);
				queue.send(new OnEnemyTurnStartedMessage());
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onGameEnded(GameResult result) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onGameEnded to " + queue);
				queue.send(new OnGameEndedMessage(result));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onGameRequest(PlayerID opponentID, String opponentName) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onGameRequest to " + queue);
				queue.send(new OnGameRequestMessage(opponentID, opponentName));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onGameRequestRefused(PlayerID opponentID) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onGameRequestRefused to " + queue);
				queue.send(new OnGameRequestRefusedMessage(opponentID));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onGameRequestWithdrawn(PlayerID opponentID) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onGameRequestWithdrawn to " + queue);
				queue.send(new OnGameRequestWithdrawnMessage(opponentID));
			} catch(JMSException e) {
				e.printStackTrace();
			}			
		}

		@Override
		public void onGameStarted() {
			
			try {
				System.out.println("SERVER WRAPPER: sending onGameStarted to " + queue);
				queue.send(new OnGameStartedMessage());
			} catch(JMSException e) {
				e.printStackTrace();
			}	
		}

		@Override
		public void onPlayerJoined(PlayerID id, String name) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onPlayerJoined to " + queue);
				queue.send(new OnPlayerJoinedMessage(id, name));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onPlayerLeft(PlayerID id) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onPlayerLeft to " + queue);
				queue.send(new OnPlayerLeftMessage(id));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onYourTurnEnded(TurnResult result) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onYourTurnEnded to " + queue);
				queue.send(new OnYourTurnEndedMessage(result));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onYourTurnStarted() {
			
			try {
				System.out.println("SERVER WRAPPER: sending onYourTurnStarted to " + queue);
				queue.send(new OnYourTurnStartedMessage());
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}
		
		@Override
		public void welcome(PlayerID givenID, String givenName) {
			
			try {
				System.out.println("SERVER WRAPPER: sending welcome to " + queue);
				queue.send(new WelcomeMessage(givenID, givenName));
			} catch(JMSException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onPlayerAddedOrRemoved(boolean added, PlayerID id, String name) {
			
			try {
				System.out.println("SERVER WRAPPER: sending onPlayerAdded to " + queue);
				queue.send(new OnPlayerAddedMessage(added, id, name));
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void onMessage(Message message) {
		
		if (message instanceof ObjectMessage) {
			
			try {
				
				if (message.getJMSReplyTo() != null) {
					
					Serializable object = ((ObjectMessage) message).getObject();
					
					if (object instanceof HelloMessage) {
						HelloMessage mes = (HelloMessage) object;
						wrappedServer.hello(new JmsClient(message.getJMSReplyTo()), mes.getName());
					} else if (object instanceof GoodbyeMessage) {
						GoodbyeMessage mes = (GoodbyeMessage) object;
						wrappedServer.goodbye(mes.getId());
					} else if (object instanceof RequestGameMessage) {
						RequestGameMessage mes = (RequestGameMessage) object;
						wrappedServer.requestGame(mes.getId());
					} else if (object instanceof WithdrawGameMessage) {
						WithdrawGameMessage mes = (WithdrawGameMessage) object;
						wrappedServer.withdrawGame(mes.getPlayerId());
					} else if (object instanceof RequestOpponentMessage) {
						RequestOpponentMessage mes = (RequestOpponentMessage) object;
						wrappedServer.requestGame(mes.getPlayerId(), mes.getOpponentId());
					} else if (object instanceof WithdrawOpponentMessage) {
						WithdrawOpponentMessage mes = (WithdrawOpponentMessage) object;
						wrappedServer.withdrawGame(mes.getPlayerID(), mes.getOpponentID());
					} else if (object instanceof AcceptGameRequestMessage) {
						AcceptGameRequestMessage mes = (AcceptGameRequestMessage) object;
						wrappedServer.acceptGameRequest(mes.getPlayerId(), mes.getOpponentId());
					} else if (object instanceof RefuseGameRequestMessage) {
						RefuseGameRequestMessage mes = (RefuseGameRequestMessage) object;
						wrappedServer.refuseGameRequest(mes.getPlayerId(), mes.getOpponentId());
					} else if (object instanceof MakeTurnMessage) {
						MakeTurnMessage mes = (MakeTurnMessage) object;
						wrappedServer.makeTurn(mes.getPlayerId(), mes.getAction());
					} else if (object instanceof SetFieldMessage) {
						SetFieldMessage mes = (SetFieldMessage) object;
						wrappedServer.setField(mes.getPlayerId(), mes.getField());
					} else {
						System.out.println("SERVER: Unknown message arrived");
					}
				} else {
					System.out.println("SERVER: Got message without JMS reply-to!");
				}
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	} 

}
